package com.kingint.web.util.tree;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;


import com.kingint.web.util.tree.TreeBo;

public class TreeUtil<T> {
    private String getidMethod;
    private String getParentidMethod;

    public TreeUtil(String GetidMethod,String GetParentidMethod) {
        this.getidMethod = GetidMethod;
        this.getParentidMethod=GetParentidMethod;
    }

    /**
     * 向下获取树结构
     *
     * @param
     * @return
     * @throws Exception
     */
    public List<T> createTree(Set<T> setall) throws Exception {
        List<T> list = new ArrayList<T>();
        Map<String, Set<T>> listhash = new HashMap<String, Set<T>>();
        if (setall == null || setall.size() == 0) {
            return null;
        }

        for (T item : setall) {
            String parentid = getParentid(item);
            if (listhash.containsKey(parentid)) {
                listhash.get(parentid).add(item);
            } else {
                Set<T> t = new HashSet<T>();
                t.add(item);
                listhash.put(parentid, t);
            }
        }
        Iterator<T> iterator = listhash.get(0l).iterator();
        while (iterator.hasNext()) {
            T item = iterator.next();
            list.add(item);
            getlow(item, listhash, list);
        }
        return list;
    }

    private void getlow(T parent, Map<String, Set<T>> list, List<T> getlist) throws Exception {
        String parentid = getid(parent);
        if (list.containsKey(parentid)) {
            Set<T> lp = list.get(parentid);
            for (T item : lp) {
                getlist.add(item);
                getlow(item, list, getlist);
            }
        }
        return;
    }

    public List<TreeBo<T>> createTreeAsTreeEntity(Set<T> setall) throws Exception {
        Map<String, Set<TreeBo<T>>> listhash = new LinkedHashMap<String, Set<TreeBo<T>>>();
        if (setall == null || setall.size() == 0) {
            return null;
        }

        for (T item : setall) {
            String parentid = getParentid(item);
            if (listhash.containsKey(parentid)) {
                TreeBo<T> et =new TreeBo<T>();
                //添加数据
                et.setTitle(item);
                listhash.get(parentid).add(et);
            } else {
                Set<TreeBo<T>> t = new LinkedHashSet<TreeBo<T>>();
                TreeBo<T> et =new TreeBo<T>();
                //添加数据
                et.setTitle(item);
                t.add(et);
                listhash.put(parentid, t);
            }
        }
        Iterator<TreeBo<T>> iterator = listhash.get("0").iterator();
        while (iterator.hasNext()) {
            TreeBo<T> entitys = iterator.next();
            getlowasTreeEntity(entitys, listhash);
        }
        return new ArrayList(listhash.get("0"));
    }
    private void getlowasTreeEntity(TreeBo<T> parent, Map<String, Set<TreeBo<T>>> list) throws Exception {
        String id = getid(parent.getTitle());
        if (list.containsKey(id)) {
            if(list.get(id)!=null){
                parent.setChildren(new ArrayList(list.get(id)));
                for(TreeBo<T> t:parent.getChildren()){
                    getlowasTreeEntity(t,list);
                }
            }
        }
    }
    /**
     * 获取父级id
     *
     * @param item
     * @return
     * @throws Exception
     */
    private String getid(T item) throws Exception {
        Method method = item.getClass().getMethod(getidMethod, null);
        Object invoke = method.invoke(item, null);
        String id = "1";
        if (invoke != null) {
            id = invoke.toString();
        }
        return id;
    }
    /**
     * 获取父级id
     *
     * @param item
     * @return
     * @throws Exception
     */
    private String getParentid(T item) throws Exception {
        Method method = item.getClass().getMethod(getParentidMethod, null);
        Object invoke = method.invoke(item, null);
        String parentid = "0";
        if (invoke != null) {
            parentid = invoke.toString();
        }
        return parentid;
    }


}